import os
import sys
from gtk import *
from gtk.gdk import Pixbuf
from xml.sax.saxutils import escape
from xmmsclient import *
from xmmsclient.collections import coll_parse
from os.path import basename
from urllib2 import url2pathname


COVER = 0
MARKUP = 1
ID = 2
VISIBLE_COL = 3

COVER_SIZE = 32

MLIB_ID = 0
MLIB_TITLE = 1
MLIB_ALBUM = 2
MLIB_ARTIST = 3
MLIB_VISIBLE = 5



class PlaylistCore:
    """PlaylistCore provides methods for Playlist that doesn't depend on 
    a gui. The primary reason PlaylistCore object exists is for 
    cleanliness of code and API. That is, there is no conceptual reason 
    all these functions could not be methods on the Playlist widget 
    instead of a separate function
    """
    name = "Current playlist"
    position = 0
    CURRENT_POSITION = None

    def __init__(self, xmms2):
        self.xmms2 = xmms2
        list = ListStore(Pixbuf, str, int, bool)
        self.playlist = list.filter_new()
        self.playlist.set_visible_column(VISIBLE_COL)
        self.xmms2.broadcast_playlist_changed(self.on_playlist_changed)

    def set_name_from_res(self, res):
        if res.iserror():
            print "[PlaylistCore]: Could not set_name"
            return
        self.name = res.value()

    def on_playlist_changed(self, res):
        if res.iserror():
            print "[playlist error]: on_playlist_changed"
            return
        val = res.value()
        type = val["type"]
        playlist = val["name"]
        if type == PLAYLIST_CHANGED_ADD:
            self.position = val["position"]
            id = val["id"]
            self.xmms2.medialib_get_info(id, self.insert_entry)
        elif type == PLAYLIST_CHANGED_CLEAR:
            model = self.playlist.get_model()
            model.clear()
        elif type == PLAYLIST_CHANGED_REMOVE:
            position = val["position"]
            model = self.playlist.get_model()
            del model[position]
        elif type == PLAYLIST_CHANGED_MOVE:
            print val
        elif type == PLAYLIST_CHANGED_UPTADE:
            print "playlist updated"
            print val
            
    def make_markup(self, url, title="", artist="", album=""):
        if not title:
            _url = url.replace("+", " ")
            path = url2pathname(_url)
            _basename = escape(basename(path))
            return basename(_basename)
        _title = escape(title)
        _artist = escape(artist)
        _album = escape(album)
        first_line = _title
        second_line = "".join(["<i>", _artist,"</i>"])
        third_line = "".join(["<i>", _album,"</i>"])
        markup = "\n".join([first_line, second_line, third_line])
        return markup
        
    def insert_entry(self, res):
        if res.iserror():
            "Could not insert entry"
            return
        info = res.value()
        try:
            id = info["id"]
        except KeyError:
            print "Error. No id key"
            return
        try:
            title = info["title"]
        except KeyError:
            title = ""
        try:
            artist = info["artist"]
        except KeyError:
            artist = ""
        try:
            album = info["album"]
        except KeyError:
            album = ""
        try:
            url = info["url"]
        except KeyError:
            print "Error!. No url key"
            return
        try:
            picture_front = info["picture_front"]
        except KeyError:
            picture_front = ""
        markup = self.make_markup(url, title, artist, album)
        row = ["", markup, id, True]
        model = self.playlist.get_model()
        if self.position:
            model.insert(self.position, row)
            self.position = None
        else:
            model.append(row)
    
    def on_load_playlist(self, res):
        if res.iserror():
            print "Could not load the playlist!"
            return
        list = res.value()
        for id in list:
            self.xmms2.medialib_get_info(id, self.insert_entry)
    
    def load_playlist(self, playlist=None):
        """Loads a playlist """
        if playlist is None:
            self.xmms2.playlist_current_active(cb=self.set_name_from_res)
        else:
            self.name = playlist
        self.xmms2.playlist_list_entries(playlist, cb=self.on_load_playlist)
        
    def force_playing(self, res):
        """Start playing. Pass if res is PLAYBACK_STATUS_PLAY"""
        if res.iserror():
            print "Could not force playing"
            return
        if res.value() != PLAYBACK_STATUS_PLAY:
            self.xmms2.playback_start()
            
    def remove_entry(self, path):
        self.xmms2.playlist_remove_entry(path)
            
    def filter(self, entry):
        query = entry.get_text().strip().lower()
        model = self.playlist.get_model()
        for row in model:
            pl_entry = row[MARKUP].lower()
            if pl_entry.find(query) > -1:
                row[VISIBLE_COL] = True
            else:
                row[VISIBLE_COL] = False



class MedialibCore:
    def __init__(self, xmms2):
        self.xmms2 = xmms2
        list = ListStore(int, str, str, str, int, bool)
        self.medialib = list.filter_new()
        self.medialib.set_visible_column(MLIB_VISIBLE)
        
    def on_load_medialib(self, res):
        if res.iserror():
            print "[MedialibCore error]: Could not load medialib"
            return
        list = res.value()
        model = self.medialib.get_model()
        for entry in list:
            row = [entry["id"]]
            for i in "title", "album", "artist":
                if entry[i] is not None:
                    row.append(entry[i])
                else:
                    row.append("")
            times_played = entry["times_played"]
            if times_played is None:
                row.append(0)
            else:
                row.append(times_played)
            row.append(True)
            model.append(row)
        
    def load_medialib(self):
        query = coll_parse("id:*")
        self.xmms2.coll_query_infos(query, 
            ("id", 
            "title", 
            "album", 
            "artist", 
            "times_played"), 
            cb=self.on_load_medialib)
            
    def filter(self, entry):
        query = entry.get_text().strip().lower()
        model = self.medialib.get_model()
        for row in model:
            title = row[MLIB_TITLE]
            artist = row[MLIB_ARTIST]
            album = row[MLIB_ALBUM]
            row[MLIB_VISIBLE] = False
            for column in title, artist, album:
                if column.lower().find(query) > -1:
                    row[MLIB_VISIBLE] = True
                    break
